package cn.fz.controller.polling;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.Collection;
import java.util.Date;

import static cn.fz.controller.polling.AsyncConfig.TIME_OUT;

@RequestMapping("polling")
@RestController
public class PollingController {
    // 存放监听某个Id的长轮询集合
    // 线程同步结构
    public static Multimap<String, DeferredResult<String>> watchRequests = Multimaps.synchronizedMultimap(HashMultimap.create());

    @RequestMapping("/index")
    public String sse() {
        return "polling";
    }

    // 设置监听
    @GetMapping("watch/{id}")
    public DeferredResult<String> watch(@PathVariable String id) {
        try {
            // 延迟对象设置超时时间
            DeferredResult<String> deferredResult = new DeferredResult<>(TIME_OUT);
            // 异步请求完成时移除key,防止内存溢出
            deferredResult.onCompletion(() -> watchRequests.remove(id, deferredResult));
            // 注册长轮询请求
            watchRequests.put(id, deferredResult);
            return deferredResult;
        } catch (AsyncRequestTimeoutException e) {
            DeferredResult<String> stringDeferredResult = new DeferredResult<>();
            stringDeferredResult.setResult("超时了");
            return stringDeferredResult;
        }
    }

    // 变更数据
    @GetMapping("publish/{id}")
    public String publish(@PathVariable String id) {
        // 数据变更 取出监听ID的所有长轮询请求,并一一响应处理
        if (watchRequests.containsKey(id)){
            Collection<DeferredResult<String>> deferredResults = watchRequests.get(id);
            for (DeferredResult<String> deferredResult : deferredResults) {
                deferredResult.setResult("我更新了 " + new Date());
            }
        }
        return "SUCCESS";
    }
}
